//-----------------------------------------------------------------------
// <copyright file="ParameterMatcher.cs" company="iron9light">
//      Copyright (c) iron9light. All rights reserved.
// </copyright>
// <author>iron9light</author>
//-----------------------------------------------------------------------

namespace EventBrokerExtension
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;

    using Microsoft.Practices.ObjectBuilder2;

    /// <summary>
    /// A utility class that handles the logic of matching parameter
    /// lists, so we can find the right method overloads.
    /// </summary>
    public class ParameterMatcher
    {
        /// <summary>
        ///  The types that this object should match.
        /// </summary>
        private readonly List<MethodParameter> parametersToMatch;

        /// <summary>
        /// Initializes a new instance of the <see cref="ParameterMatcher"/> class
        /// that will attempt to match the given parameter types.
        /// </summary>
        /// <param name="parametersToMatch">Target parameters to match against.</param>
        public ParameterMatcher(IEnumerable<MethodParameter> parametersToMatch)
        {
            this.parametersToMatch = new List<MethodParameter>(parametersToMatch);
        }

        /// <summary>
        /// Tests to see if the given set of types matches the ones
        /// we're looking for.
        /// </summary>
        /// <param name="candidate">parameter list to look for.</param>
        /// <returns>true if they match, false if they don't.</returns>
        public virtual bool Matches(IEnumerable<Type> candidate)
        {
            List<Type> candidateTypes = new List<Type>(candidate);
            if (this.parametersToMatch.Count == candidateTypes.Count)
            {
                for (int i = 0; i < this.parametersToMatch.Count; ++i)
                {
                    if (!this.parametersToMatch[i].MatchesType(candidateTypes[i]))
                    {
                        return false;
                    }
                }

                return true;
            }

            return false;
        }

        /// <summary>
        /// Tests to see if the given set of types matches the ones we're looking for.
        /// </summary>
        /// <param name="candidate">Candidate method signature to look for.</param>
        /// <returns>True if they match, false if they don't.</returns>
        public virtual bool Matches(IEnumerable<ParameterInfo> candidate)
        {
            return this.Matches(
                    Sequence.Map<ParameterInfo, Type>(
                            candidate,
                            delegate(ParameterInfo pi)
                            {
                                return pi.ParameterType;
                            }));
        }
    }
}